package com.youlu.campus.service.english;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.AtomicDouble;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.entity.*;
import com.youlu.campus.entity.VO.res.QaInfoScoreResponse;
import com.youlu.campus.entity.VO.res.QaRuleMatchRes;
import com.youlu.campus.entity.english.*;
import com.youlu.campus.entity.english.vo.request.DoQaCommand;
import com.youlu.campus.entity.english.vo.request.QueryQaCommand;
import com.youlu.campus.entity.english.vo.response.UserQaInfoResponse;
import com.youlu.campus.entity.english.vo.response.UserQaScoreResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.SetUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CompetitionQaInfoService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private UserCompetitionFeeService userCompetitionFeeService;

    private final static String QA = "QA";

    private final static String PRACTICE = "PRACTICE";

    @Autowired
    private UserCompetitionQaService userCompetitionQaService;

    @Autowired
    private UserCompetitionQaCaService userCompetitionQaCaService;

    @Autowired
    private UserCompetitionService userCompetitionService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    private final static String USER_QA_LOCK = "campus:english:qa:lock:%s:%s";

    public UserQaScoreResponse doQa(DoQaCommand doQaCommand) {
        String qaType = doQaCommand.getQaType();
        String activityGroupId = doQaCommand.getActivityGroupId();
        String qaInfoId = doQaCommand.getQaInfoId();
        UserPO currentUser = doQaCommand.getCurrentUser();
        String userId = currentUser.getId();
        String feeTypeCode = doQaCommand.getFeeTypeCode();
        List<ActivityQuestionInfo> userAnswersQuestionInfoList = doQaCommand.getUserAnswersQuestionInfoList();
        //List<ActivityAnswerInfo> userAnswersList = doQaCommand.getUserAnswersList();
        log.info("当前用户 - >{} 提交了 qaInfoId - > {} 答题 - > {} ", currentUser.getId(), qaInfoId,
                userAnswersQuestionInfoList.size());
        Boolean existLockKey = redisTemplate.opsForValue().setIfAbsent(String.format(USER_QA_LOCK, userId, qaInfoId),
                "1", 3L, TimeUnit.SECONDS);
        log.info("【英语竞赛-提交答题】获取锁状态->{}", existLockKey);
        if (Objects.nonNull(existLockKey) && !existLockKey) {
            throw new BusinessException("对不起哦，服务繁忙,稍后重试");
        }
        List<String> userSubmitQuestionIdList =
                userAnswersQuestionInfoList.stream().map(userAnswer -> userAnswer.getId()).collect(Collectors.toList());
        Query query = new Query();
        query.addCriteria(Criteria.where("id").in(userSubmitQuestionIdList));
        query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
        List<ActivityQuestionInfo> questionInfoList = this.mongoTemplate.find(query, ActivityQuestionInfo.class);
        if (CollectionUtils.isEmpty(questionInfoList)) {
            throw new BusinessException("未找到答题信息");
        }
        ActivityQaInfo activityQaInfo = this.mongoTemplate.findById(qaInfoId, ActivityQaInfo.class);
        Long qaCount = userCompetitionQaService.qaCount(userId, qaInfoId, 1);
        if (qaCount <= 0L) {
            throw new BusinessException("对不起,答题次数已用完，已不能再次参加答题");
        }
        UserQaScoreResponse userQaScore = new UserQaScoreResponse();
        userQaScore.setActivityGroupId(activityGroupId);
        userQaScore.setQaInfoId(qaInfoId);
        userQaScore.setQaCode(doQaCommand.getQaCode());
        switch (qaType) {
            case QA:
                QaInfoScoreResponse userQaInfoScore = getQaScore(currentUser.getId(), qaInfoId, questionInfoList,
                        userAnswersQuestionInfoList);
                Double qaScore = userQaInfoScore.getQaScore();
                userQaInfoScore.getUserAnswersErrorQuestionInfoList().clear();
                userQaInfoScore.getUserAnswersRightQuestionInfoList().clear();
                log.info("【英语大赛】用户->{}参与了题目->{} | 答题 - > {} | 分数->{}", currentUser.getId(), qaInfoId, qaScore);
                QaRuleMatchRes qaRuleMatchRes = qaRuleByQaInfoId(qaInfoId, qaScore);
                String caLevelName = qaRuleMatchRes.getCaLevelName();
                log.info("【英语大赛】用户->{}参与了题目->{} | 答题 - > {} | 分数->{} 等级 - > {}", currentUser.getId(), qaInfoId,
                        qaScore, caLevelName);
                userQaScore.setScore(qaScore.toString() + "分");
                userQaScore.setCaLevel(caLevelName);
                Double passQaScore = activityQaInfo.getPassQaScore();
                if (qaScore.intValue() >= passQaScore.intValue()) {
                    // 更新保存答题分数信息
                    query = new Query();
                    query.addCriteria(Criteria.where("userId").is(userId));
                    query.addCriteria(Criteria.where("qaInfoId").is(qaInfoId));
                    query.addCriteria(Criteria.where("activityGroupId").is(activityGroupId));
                    query.addCriteria(Criteria.where("qaCode").is(doQaCommand.getQaCode()));
                    //query.addCriteria(Criteria.where("qaLimit").gte(0));
                    Update update = new Update();
                    ScoreMappingLevel scoreMappingLevel = new ScoreMappingLevel();
                    scoreMappingLevel.setScore(qaScore);
                    scoreMappingLevel.setLevel(caLevelName);
                    update.push("qaScoreLevelList", scoreMappingLevel);
                    update.set("score", qaScore);
                    update.set("caLevel", caLevelName);
                    update.inc("qaLimit", -1);
                    update.set("updatedTime", new Date());
                    this.mongoTemplate.updateFirst(query, update, UserCompetitionQa.class);
                    //更新解锁答题
                    userCompetitionFeeService.updateByQaType(currentUser.getId(), activityGroupId, feeTypeCode,
                            qaInfoId, doQaCommand.getQaCode());
                    ActivityGroup activityGroup = this.mongoTemplate.findById(activityGroupId, ActivityGroup.class);
                    Optional<ActivityGroupQaType> qaTypeOptional =
                            activityGroup.getQaTypeList().stream().filter(qaGroup -> qaGroup.getQaInfoId().equals(qaInfoId)).findFirst();
                    if (qaTypeOptional.isPresent()) {
                        ActivityGroupQaType activityGroupQaType = qaTypeOptional.get();
                        userQaScore.setTipsScore("恭喜，获" + activityGroupQaType.getName() + caLevelName + "证书");
                        userQaScore.setButtonText("领取" + activityGroupQaType.getName() + "证书");
                        UserCompetitionQaCa qaCa = new UserCompetitionQaCa();
                        qaCa.setUserId(currentUser.getId());
                        qaCa.setActivityGroupId(activityGroupId);
                        qaCa.setActivityGroupName(activityGroup.getGroupName());
                        qaCa.setCaLevel(caLevelName);
                        qaCa.setCaType(activityGroupQaType.getAliasName());
                        userQaScore.setCaType(activityGroupQaType.getAliasName());
                        qaCa.setActivityId(activityGroup.getActivityId());
                        userQaScore.setCaReceive(Boolean.TRUE);
                        userCompetitionQaCaService.save(qaCa);
                    }
                } else {
                    userQaScore.setTipsScore("很遗憾,未获奖");
                    userQaScore.setButtonText("重新答题");
                    userQaScore.setRestQa(Boolean.TRUE);
                }
                UserCompetitionQaAnswer userCompetitionQa = new UserCompetitionQaAnswer();
                userCompetitionQa.setActivityGroupId(activityGroupId);
                userCompetitionQa.setAnswersQuestionInfoList(userAnswersQuestionInfoList);
                userCompetitionQa.setQaInfoId(qaInfoId);
                userCompetitionQa.setUserId(currentUser.getId());
                userCompetitionQa.setQaCode(doQaCommand.getQaCode());
                userCompetitionQa.setScore(qaScore);
                this.mongoTemplate.save(userCompetitionQa);
                //移除选题
                query = new Query();
                query.addCriteria(Criteria.where("userId").is(userId));
                query.addCriteria(Criteria.where("activityQaInfoId").is(activityQaInfo.getId()));
                query.addCriteria(Criteria.where("activityGroupId").is(activityGroupId));
                this.mongoTemplate.remove(query, UserQuestionInfo.class);
                userCompetitionQaService.qaCount(userId, qaInfoId, -1);
                break;
            case PRACTICE:
                break;
        }
        return userQaScore;

    }

    public QaRuleMatchRes qaRuleByQaInfoId(String qaInfoId, Double score) {
        QaRuleMatchRes qaRuleMatchRes = new QaRuleMatchRes();
        Query query = new Query();
        query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
        query.with(Sort.by(Sort.Direction.DESC, "priority"));
        List<ActivityQaRule> qaRuleList = this.mongoTemplate.find(query, ActivityQaRule.class);
        if(CollectionUtils.isEmpty(qaRuleList)){
            return qaRuleMatchRes;
        }
        ActivityQaRule activityQaRuleMax = qaRuleList.get(0);
        Optional<ActivityQaRule> sectionOptional =
                qaRuleList.stream().filter(rewardRule -> ActivityRewardRule.SECTION.equals(rewardRule.getInviteOperatorType()) && (score.intValue() >= rewardRule.getQaStart().intValue() && score.intValue() <= rewardRule.getQaEnd().intValue())).findAny();
        if (sectionOptional.isPresent()) {
            ActivityQaRule activityRewardRule = sectionOptional.get();
            if (activityQaRuleMax.getPriority() == activityRewardRule.getPriority()) {
                qaRuleMatchRes.setHighestLevel(Boolean.TRUE);
            }
            qaRuleMatchRes.setCaLevelName(activityRewardRule.getCaName());
            return qaRuleMatchRes;
        }

        Optional<ActivityQaRule> rightIntervalOptional =
                qaRuleList.stream().filter(rewardRule -> ActivityRewardRule.RIGHT_INTERVAL.equals(rewardRule.getInviteOperatorType()) && (score.intValue() >= rewardRule.getQaEnd().intValue())).findAny();
        if (rightIntervalOptional.isPresent()) {
            ActivityQaRule activityRewardRule = rightIntervalOptional.get();
            qaRuleMatchRes.setCaLevelName(activityRewardRule.getCaName());
            if (activityQaRuleMax.getPriority() == activityRewardRule.getPriority()) {
                qaRuleMatchRes.setHighestLevel(Boolean.TRUE);
            }
            return qaRuleMatchRes;
        }

        Optional<ActivityQaRule> equalsOptional =
                qaRuleList.stream().filter(rewardRule -> ActivityRewardRule.EQUALS.equals(rewardRule.getInviteOperatorType()) && (rewardRule.getQaEnd().intValue() == score.intValue())).findAny();
        if (equalsOptional.isPresent()) {
            ActivityQaRule activityRewardRule = equalsOptional.get();
            qaRuleMatchRes.setCaLevelName(activityRewardRule.getCaName());
            if (activityQaRuleMax.getPriority() == activityRewardRule.getPriority()) {
                qaRuleMatchRes.setHighestLevel(Boolean.TRUE);
            }
            return qaRuleMatchRes;
        }
        Optional<ActivityQaRule> leftIntervalOptional =
                qaRuleList.stream().filter(rewardRule -> ActivityRewardRule.LEFT_INTERVAL.equals(rewardRule.getInviteOperatorType()) && (score.intValue() <= rewardRule.getQaEnd().intValue())).findAny();
        if (leftIntervalOptional.isPresent()) {
            ActivityQaRule activityRewardRule = leftIntervalOptional.get();
            qaRuleMatchRes.setCaLevelName(activityRewardRule.getCaName());
            if (activityQaRuleMax.getPriority() == activityRewardRule.getPriority()) {
                qaRuleMatchRes.setHighestLevel(Boolean.TRUE);
            }
            return qaRuleMatchRes;
        }
        return qaRuleMatchRes;
    }

    public QaInfoScoreResponse getQaScore(String userId, String qaInfoId, List<ActivityQuestionInfo> questionInfoList,
                                          List<ActivityQuestionInfo> userAnswersQuestionInfoList) {
        AtomicDouble totalScore = new AtomicDouble(0D);
        //答题错误题数
        AtomicInteger qaErrorCount = new AtomicInteger(0);
        //答题正确题数
        AtomicInteger qaRightCount = new AtomicInteger(0);
        //记录用户选择错误记录
        List<ActivityQuestionInfo> userAnswersErrorQuestionInfoList = Lists.newLinkedList();
        //记录用户选择正确记录
        List<ActivityQuestionInfo> userAnswersRightQuestionInfoList = Lists.newLinkedList();
        questionInfoList.stream().forEach(questionInfo -> {
            //获取提型1、单选 0 多选
            Integer type = questionInfo.getType();
            List<ActivityAnswerInfo> answerInfoList = findByQuestionId(questionInfo.getId());
            //判断答题与用户提交答题是否同一套
            Optional<ActivityQuestionInfo> userAnswersQuestionInfoOptional =
                    userAnswersQuestionInfoList.stream().filter(userAnswersQuestionInfo -> userAnswersQuestionInfo.getId().equals(questionInfo.getId())).findAny();
            if (!userAnswersQuestionInfoOptional.isPresent()) {
                return;
            }
            ActivityQuestionInfo userAnswersQuestionInfo = userAnswersQuestionInfoOptional.get();
            List<ActivityAnswerInfo> userAnswerInfoList = userAnswersQuestionInfo.getAnswerInfos();
            Double score = questionInfo.getScore();
            //如果是单选操作
            if (type == 1) {
                Optional<ActivityAnswerInfo> rightAnswerOptional =
                        answerInfoList.stream().filter(answerInfo -> answerInfo.getAnswered()).findAny();
                if (!rightAnswerOptional.isPresent()) {
                    return;
                }
                // 题目的答案
                ActivityAnswerInfo rightAnswerInfo = rightAnswerOptional.get();
                long count = userAnswerInfoList.stream().filter(userAnswerInfo -> userAnswerInfo.getAnswered().equals(rightAnswerInfo.getAnswered()) && rightAnswerInfo.getId().equals(userAnswerInfo.getId())).count();
                if (count > 0) {
                    log.info("【答题正确-单选】用户->{} 单选题参与了题目->{} | 答题 - > {} 答案与配置一致", userId, qaInfoId,
                            questionInfo.getId());
                    totalScore.addAndGet(score);
                    qaRightCount.incrementAndGet();
                    questionInfo.setAnswerInfos(answerInfoList);
                    questionInfo.setUserQaRight(Boolean.TRUE);
                    questionInfo.setUserQaItem(rightAnswerInfo.getPriority().toString());
                    questionInfo.setRightQaItem(rightAnswerInfo.getPriority().toString());
                    userAnswersRightQuestionInfoList.add(questionInfo);
                } else {
                    //获取用户错误选项
                    ActivityAnswerInfo userQaErrorAnswerInfo =
                            userAnswerInfoList.stream().filter(userAnswerInfo -> userAnswerInfo.getAnswered()).findFirst().orElse(null);
                    if (Objects.nonNull(userQaErrorAnswerInfo)) {
                        userAnswersQuestionInfo.setUserQaItem(userQaErrorAnswerInfo.getPriority().toString());
                        answerInfoList.forEach(answerInfo -> {
                            answerInfo.setAnswered(Boolean.FALSE);
                            if(userQaErrorAnswerInfo.getAnswered()&&answerInfo.getId().equals(userQaErrorAnswerInfo.getId())){
                                answerInfo.setAnswered(userQaErrorAnswerInfo.getAnswered());
                            }
                        });
                        userAnswersQuestionInfo.setAnswerInfos(answerInfoList);
                    }
                    //获取正确答案
                    userAnswersQuestionInfo.setRightQaItem(rightAnswerInfo.getPriority().toString());
                    //获取答题解析
                    userAnswersQuestionInfo.setQaAnalysis(questionInfo.getQaAnalysis());
                    userAnswersErrorQuestionInfoList.add(userAnswersQuestionInfo);
                    log.info("【答题错误-单选】用户->{} 单选题 参与了题目->{} | 答题 - > {} 答错误题", userId, qaInfoId, questionInfo.getId());
                    qaErrorCount.incrementAndGet();
                }
            } else {
                //多选题
                Set<ActivityAnswerInfo> rightAnswerInfoSet =
                        answerInfoList.stream().filter(activityAnswerInfo -> activityAnswerInfo.getAnswered()).map(activityAnswerInfo -> {
                            ActivityAnswerInfo rightAnswerInfo = new ActivityAnswerInfo();
                            rightAnswerInfo.setAnswered(activityAnswerInfo.getAnswered());
                            rightAnswerInfo.setId(activityAnswerInfo.getId());
                            rightAnswerInfo.setPriority(activityAnswerInfo.getPriority());
                            return rightAnswerInfo;
                        }).collect(Collectors.toSet());
                Set<ActivityAnswerInfo> userAnswerInfoSet =
                        userAnswerInfoList.stream().filter(userAnswerInfo ->userAnswerInfo.getAnswered()).map(userAnswers -> {
                            ActivityAnswerInfo userAnswerInfo = new ActivityAnswerInfo();
                            userAnswerInfo.setAnswered(userAnswers.getAnswered());
                            userAnswerInfo.setId(userAnswers.getId());
                            userAnswerInfo.setPriority(userAnswers.getPriority());
                            return userAnswerInfo;
                        }).collect(Collectors.toSet());
                if (SetUtils.isEqualSet(rightAnswerInfoSet, userAnswerInfoSet)) {
                    log.info("【答题正确-多选】用户->{} 参与多选题->{} | 答题 - > {} 答案与配置一致", userId, qaInfoId, questionInfo.getId());
                    totalScore.addAndGet(score);
                    qaRightCount.incrementAndGet();
                    //获取用户正确选项
                    String userQaItem = rightAnswerInfoSet.stream().filter(userAnswerInfo -> userAnswerInfo.getAnswered()).map(userAnswerInfo -> userAnswerInfo.getPriority().toString()).collect(Collectors.joining(","));
                    answerInfoList.stream().forEach(userAnswerInfo->{
                        long count = rightAnswerInfoSet.stream().filter(rightAnswerInfo -> userAnswerInfo.getId().equals(rightAnswerInfo.getId()) && rightAnswerInfo.getAnswered()).count();
                        if(count>0){
                            userAnswerInfo.setAnswered(Boolean.TRUE);
                        }
                    });
                    questionInfo.setAnswerInfos(answerInfoList);
                    questionInfo.setUserQaRight(Boolean.TRUE);
                    questionInfo.setUserQaItem(userQaItem);
                    questionInfo.setRightQaItem(userQaItem);
                    userAnswersRightQuestionInfoList.add(questionInfo);
                } else {
                    //获取用户多选错误选项
                    String userQaItem =
                            userAnswerInfoList.stream().filter(userAnswerInfo -> userAnswerInfo.getAnswered()).map(userAnswerInfo -> userAnswerInfo.getPriority().toString()).collect(Collectors.joining(","));
                    userAnswersQuestionInfo.setUserQaItem(userQaItem);
                    //获取正确答案
                    String rightQaItem =
                            answerInfoList.stream().filter(userAnswerInfo -> userAnswerInfo.getAnswered()).map(userAnswerInfo -> userAnswerInfo.getPriority().toString()).collect(Collectors.joining(","));
                    userAnswersQuestionInfo.setRightQaItem(rightQaItem);
                    //获取答题解析
                    userAnswersQuestionInfo.setQaAnalysis(questionInfo.getQaAnalysis());
                    userAnswersQuestionInfo.setAnswerInfos(answerInfoList);
                    userAnswersErrorQuestionInfoList.add(userAnswersQuestionInfo);
                    log.info("【答题错误-多选】用户->{} 参与多选题 参与了题目->{} | 答题 - > {} 答错误题", userId, qaInfoId,
                            questionInfo.getId());
                    qaErrorCount.incrementAndGet();
                }
            }
        });
        log.info("【答题结束】用户-> {} 参与答题结果-> {}正确->{} 错误-> [} 得分-> {}", userId, qaInfoId, qaRightCount.get(),
                qaErrorCount.get(), totalScore.doubleValue());
        QaInfoScoreResponse qaInfoScoreResponse = new QaInfoScoreResponse();
        qaInfoScoreResponse.setQaScore(totalScore.doubleValue());
        qaInfoScoreResponse.setQaErrorCount(qaErrorCount.get());
        qaInfoScoreResponse.setQaRightCount(qaRightCount.get());
        qaInfoScoreResponse.setUserAnswersErrorQuestionInfoList(userAnswersErrorQuestionInfoList);
        qaInfoScoreResponse.setUserAnswersRightQuestionInfoList(userAnswersRightQuestionInfoList);
        return qaInfoScoreResponse;
    }


    private List<ActivityAnswerInfo> findByQuestionId(String questionId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("activityQuestionId").is(questionId));
        query.with(Sort.by(Sort.Direction.ASC, "priority"));
        return this.mongoTemplate.find(query, ActivityAnswerInfo.class);
    }


    public UserQaInfoResponse findByQaInfoId(QueryQaCommand queryQaCommand) {
        String activityGroupId = queryQaCommand.getActivityGroupId();
        String qaInfoId = queryQaCommand.getQaInfoId();
        Integer pageNo = queryQaCommand.getPageNo();
        Integer pageSize = queryQaCommand.getPageSize();
        String qaType = queryQaCommand.getQaType();
        String feeTypeCode = queryQaCommand.getFeeTypeCode();
        UserPO currentUser = queryQaCommand.getCurrentUser();
        log.info("【答题】userId -> {} | groupId -> {}| qaType - > {} | qaInfo->{} ", currentUser.getId(),
                activityGroupId, qaType, qaInfoId);
        UserCompetitionFee userCompetitionFee = null;
        if (ActivityQaFeeDetail.BAO_MING_QA_FEE.equals(feeTypeCode)) {
            userCompetitionFee = userCompetitionFeeService.verificationUserFee(currentUser.getId(), activityGroupId,
                    feeTypeCode);
            if (Objects.isNull(userCompetitionFee)) {
                List<UserCompetitionFee> userCompetitionFeeList =
                        userCompetitionFeeService.userBuyfindActivityGroupId(currentUser.getId(), activityGroupId);
                if (CollectionUtils.isEmpty(userCompetitionFeeList)) {
                    throw new BusinessException("对不起，您未购买，无权限参与答题");
                }
                Optional<UserCompetitionFee> baoMingFeeOptional =
                        userCompetitionFeeList.stream().filter(userFee -> ActivityQaFeeDetail.BAO_MING_FEE.equals(userFee.getFeeTypeCode())).findFirst();
                if (baoMingFeeOptional.isPresent()) {
                    userCompetitionFee = baoMingFeeOptional.get();
                }
            }
        } else {
            userCompetitionFee = userCompetitionFeeService.verificationUserFee(currentUser.getId(),
                    activityGroupId, feeTypeCode);
            if (Objects.isNull(userCompetitionFee)) {
                throw new BusinessException("对不起，您未购买，无权限参与答题");
            }
        }
        ActivityQaInfo activityQaInfo = this.mongoTemplate.findById(qaInfoId, ActivityQaInfo.class);
        if (Objects.isNull(activityQaInfo)) {
            throw new BusinessException("答题不存在");
        }

        UserQaInfoResponse userQaInfoResponse = new UserQaInfoResponse();
        userQaInfoResponse.setActivityGroupId(activityGroupId);
        userQaInfoResponse.setQaInfoId(qaInfoId);
        userQaInfoResponse.setFeeTypeCode(feeTypeCode);
        userQaInfoResponse.setQaType(qaType);
        userQaInfoResponse.setLimitTimed(activityQaInfo.getLimitTimed());
        userQaInfoResponse.setLimitTime(activityQaInfo.getLimitTime());
        userQaInfoResponse.setQaCode(queryQaCommand.getQaCode());
        userQaInfoResponse.setQaSystemNumber(activityQaInfo.getQaSystemNumber());
        UserQuestionInfo userQuestionInfo = null;
        Query query = new Query();
        query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
        query.with(Sort.by(Sort.Direction.ASC, "priority"));
        List<ActivityQuestionInfo> qaList = this.mongoTemplate.find(query, ActivityQuestionInfo.class);
        switch (qaType) {
            case QA:
                if (!ActivityQaFeeDetail.QA_FEE.equals(feeTypeCode)) {
                    List<ActivityGroupQaType> buyQaTypeList = userCompetitionFee.getBuyQaTypeList();
                    long count =
                            buyQaTypeList.stream().filter(qa -> qa.getQaInfoId().equals(qaInfoId) && qa.getLock()).count();
                    if (count == 0) {
                        throw new BusinessException("对不起，您无权限参与答题");
                    }
                }
                //判断答题次数
                Long qaCount = userCompetitionQaService.qaCount(currentUser.getId(), qaInfoId, 1);
                if (qaCount <= 0L) {
                    throw new BusinessException("对不起,答题次数已用完，已不能再次参加答题");
                }
                query = new Query();
                query.addCriteria(Criteria.where("userId").is(currentUser.getId()));
                query.addCriteria(Criteria.where("qaInfoId").is(qaInfoId));
                query.addCriteria(Criteria.where("activityGroupId").is(activityGroupId));
                query.addCriteria(Criteria.where("qaCode").is(queryQaCommand.getQaCode()));
                UserCompetitionQa userCompetitionQa = this.mongoTemplate.findOne(query, UserCompetitionQa.class);
                if (Objects.isNull(userCompetitionQa)) {
                    userCompetitionQa = new UserCompetitionQa();
                    userCompetitionQa.setUserId(currentUser.getId());
                    userCompetitionQa.setQaInfoId(qaInfoId);
                    userCompetitionQa.setActivityGroupId(activityGroupId);
                    ActivityGroup activityGroup = this.mongoTemplate.findById(activityGroupId, ActivityGroup.class);
                    userCompetitionQa.setActivityGroupName(activityGroup.getGroupName());
                    userCompetitionQa.setQaLimit(activityQaInfo.getTotalQaNum());
                    userCompetitionQa.setQaCode(queryQaCommand.getQaCode());
                    userCompetitionQa.setQaType(qaType);
                    UserCompetition userCompetition = userCompetitionService.findByUserId(currentUser.getId());
                    if (Objects.nonNull(userCompetition)) {
                        userCompetitionQa.setNickName(userCompetition.getNickName());
                        userCompetitionQa.setAvatarUrl(userCompetition.getAvatarUrl());
                        userCompetitionQa.setUniversityId(userCompetition.getUniversityId());
                        userCompetitionQa.setUniversityName(userCompetition.getUniversityName());
                    }
                    this.mongoTemplate.save(userCompetitionQa);
                }
                userQaInfoResponse.setTotalQaNum(qaCount.intValue());
                query = new Query();
                query.addCriteria(Criteria.where("userId").is(currentUser.getId()));
                query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
                query.addCriteria(Criteria.where("activityGroupId").is(activityGroupId));
                userQuestionInfo = this.mongoTemplate.findOne(query, UserQuestionInfo.class);
                if (Objects.nonNull(userQuestionInfo)) {
                    int totalSize = userQuestionInfo.getQuestionInfoList().size();
                    List<ActivityQuestionInfo> questionInfoList = userQuestionInfo.getQuestionInfoList();
                    userQaInfoResponse.setQuestionInfo(questionInfoPage(pageNo, pageSize, totalSize, questionInfoList));
                    return userQaInfoResponse;
                }
                qaBuild(pageNo, pageSize, currentUser, activityQaInfo, qaList, userQaInfoResponse);
                return userQaInfoResponse;
            case PRACTICE:
                Integer[] index = {1};
                qaList.stream().peek(questionInfo -> questionInfo.setPriority(index[0]++)).collect(Collectors.toList());
                qaList.stream().map(questionInfo -> {
                    questionInfo.setAnswerInfos(findByQuestionId2(questionInfo.getId(), Boolean.FALSE));
                    return questionInfo;
                }).collect(Collectors.toList());
                userQaInfoResponse.setQuestionInfo(questionInfoPage(pageNo, pageSize, qaList.size(), qaList));
                return userQaInfoResponse;
            default:
        }
        return userQaInfoResponse;
    }

    /**
     * 后续优化
     *
     * @param pageNo
     * @param pageSize
     * @param currentUser
     * @param activityQaInfo
     * @param qaList
     * @param userQaInfoResponse
     */
    public void qaBuild(Integer pageNo, Integer pageSize, UserPO currentUser, ActivityQaInfo activityQaInfo,
                        List<ActivityQuestionInfo> qaList, UserQaInfoResponse userQaInfoResponse) {
        Boolean randomQa = activityQaInfo.getRandomQa();
        //是否随机选题
        if (randomQa) {
            log.info("随机选题->{}", activityQaInfo.getActivityName());
            List<ActivityQuestionInfo> questionInfoList = new ArrayList<>();
            //随机单选题数量
            Integer randomRadioQaCount = activityQaInfo.getRandomRadioQaCount();
            List<ActivityQuestionInfo> randomRadioQaList =
                    qaList.stream().filter(questionInfo -> questionInfo.getType() == 1).collect(Collectors.toList());
            randomQuestionInfo(randomRadioQaCount, questionInfoList, randomRadioQaList);
            //随机多选题数量
            Integer randomMultiQaCount = activityQaInfo.getRandomMultiQaCount();
            List<ActivityQuestionInfo> randomMultiQaList =
                    qaList.stream().filter(questionInfo -> questionInfo.getType() == 0).collect(Collectors.toList());
            randomQuestionInfo(randomMultiQaCount, questionInfoList, randomMultiQaList);
            Integer[] index = {1};
            List<ActivityQuestionInfo> orderList =
                    questionInfoList.stream().peek(questionInfo -> questionInfo.setPriority(index[0]++)).collect(Collectors.toList());
            orderList.stream().map(questionInfo -> {
                List<ActivityAnswerInfo> answerInfoList = this.findByQuestionId(questionInfo.getId());
                questionInfo.setAnswerInfos(answerInfoList.stream().map(activityAnswerInfo -> {
                    activityAnswerInfo.setAnswered(Boolean.FALSE);
                    return activityAnswerInfo;
                }).collect(Collectors.toList()).stream().sorted(Comparator.comparing(ActivityAnswerInfo::getPriority)).collect(Collectors.toList()));
                questionInfo.setQaSystemNumber(activityQaInfo.getQaSystemNumber());
                return questionInfo;
            }).collect(Collectors.toList());
            if (userQaInfoResponse.getType() != 1) {
                UserQuestionInfo userQuestionInfo = new UserQuestionInfo();
                userQuestionInfo.setUserId(currentUser.getId());
                userQuestionInfo.setActivityQaInfoId(userQaInfoResponse.getQaInfoId());
                userQuestionInfo.setQuestionInfoList(orderList);
                userQuestionInfo.setActivityId(activityQaInfo.getActivityId());
                userQuestionInfo.setActivityGroupId(userQaInfoResponse.getActivityGroupId());
                this.mongoTemplate.save(userQuestionInfo);
            }
            userQaInfoResponse.setQuestionInfo(this.questionInfoPage(pageNo, pageSize, orderList.size(), orderList));
        } else {
            Integer[] index = {1};
            qaList.stream().peek(questionInfo -> questionInfo.setPriority(index[0]++)).collect(Collectors.toList());
            qaList.stream().map(questionInfo -> {
                questionInfo.setAnswerInfos(findByQuestionId2(questionInfo.getId(), Boolean.TRUE));
                questionInfo.setQaSystemNumber(activityQaInfo.getQaSystemNumber());
                return questionInfo;
            }).collect(Collectors.toList());
            userQaInfoResponse.setQuestionInfo(questionInfoPage(pageNo, pageSize, qaList.size(), qaList));
        }

    }

    private List<ActivityAnswerInfo> findByQuestionId2(String questionId, Boolean qa) {
        List<ActivityAnswerInfo> answerInfoList = this.findByQuestionId(questionId);
        if (CollectionUtils.isEmpty(answerInfoList)) {
            throw new BusinessException("未配置问题");
        }
        return answerInfoList.stream().map(activityAnswerInfo -> {
            if (qa) {
                activityAnswerInfo.setAnswered(Boolean.FALSE);
            }
            return activityAnswerInfo;
        }).sorted(Comparator.comparing(ActivityAnswerInfo::getPriority)).collect(Collectors.toList());
    }

    private void randomQuestionInfo(Integer randomCount, List<ActivityQuestionInfo> questionInfoList,
                                    List<ActivityQuestionInfo> randomQuestionInfoList) {
        log.info("random - > {}", randomCount);
        if (CollectionUtils.isEmpty(randomQuestionInfoList)||(Objects.isNull(randomCount)||randomCount ==0)) {
            log.warn("random  答题数量为 -  > {} ", randomCount);
            return;
        }
        log.info("randomShuffle - > {}", randomQuestionInfoList.size());
        Collections.shuffle(randomQuestionInfoList);
        if (randomCount >= 1) {
            log.info("随机生成题库 - > {} 随机数-> {}", randomQuestionInfoList.size(), randomCount);
            if (randomQuestionInfoList.size() > randomCount) {
                questionInfoList.addAll(randomQuestionInfoList.subList(0, randomCount));
                return;
            }
        }
        questionInfoList.addAll(randomQuestionInfoList);
    }

    public Page<ActivityQuestionInfo> questionInfoPage(Integer pageNo, Integer pageSize, Integer totalCount,
                                                       List<ActivityQuestionInfo> questionInfoList) {
        PageRequest pageRequest = PageRequest.of(pageNo - 1, pageSize);
        List<ActivityQuestionInfo> newPage =
                questionInfoList.stream().skip((pageNo - 1) * pageSize).limit(pageSize).sorted(Comparator.comparing(ActivityQuestionInfo::getPriority)).collect(Collectors.toList());
        return PageableExecutionUtils.getPage(newPage, pageRequest, () -> totalCount);
    }

    private List<ActivityQuestionInfo> getActivityQuestionInfos(String qaInfoId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
        query.with(Sort.by(Sort.Direction.ASC, "priority"));
        return this.mongoTemplate.find(query, ActivityQuestionInfo.class);
    }
}
